#include"treeMaker.h"
node_t* getNum(program* p)
{
    node_t* n = NULL;
    if(p->lex[GL_pos].lexType == NUMBER)
        {n = newNode(&(p->lex[GL_pos]), 0, NULL, NULL);GL_pos++;}
//printTree(n);
//printf("/ngetT[%p]", n);
//printTree(n);
    return n;
}
node_t* getP(program* p)
{
    node_t* n = NULL;
    if(p->lex[GL_pos].opType == BR_OP)
    {
        GL_pos++;
        n = getE(p);
        if(p->lex[GL_pos].opType == BR_CL)
            GL_pos++;
//printTree(n);
        return n;
    }
    else if (p->lex[GL_pos].lexType == NUMBER)
    {
        n = getNum(p);
//printTree(n);
        return n;
    }
    else if(p->lex[GL_pos].opType == VARIABLE)
    {
        n = getV(p);
        if(p->lex[GL_pos].lexType == OPERATOR && p->lex[GL_pos].opType == BR_OP)
            n->right = getF(p);
//printTree(n);
        return n;
    }
}
node_t* getE(program* p)
{
    node_t* t = getT(p);
//printf("getE[%p], pos[%d]", t, GL_pos);
//printTree(t);
    lexeme* l;
    while(p->lex[GL_pos].lexType == OPERATOR &&
    (p->lex[GL_pos].opType == ADD || p->lex[GL_pos].opType == MINUS_BIN))
    {
        l = &(p->lex[GL_pos]);
        GL_pos++;
        t = newNode(l, 0, t, getT(p));
    }
//printTree(t);
    return t;
}
node_t* getG(program* p)
{
    GL_pos = 0;
//printf("YOLO");
    if(p == NULL)
        return NULL;
    node_t* n = getPr(p);
//printTree(n);
    if (p->lex[GL_pos].opType == EOPR
       || p->lex[GL_pos+1].opType == EOPR)
        return n;
    else
    {
        //syntaxError Log;
        printf("\nERROR: lexeme[%d]", GL_pos);
        return NULL;
    }
}
node_t* getV(program* p)
{
    if(p->lex[GL_pos].lexType != VARIABLE && p->lex[GL_pos].lexType != FUNCTION)
        return NULL;

    lexeme* l = &(p->lex[GL_pos]);

    int num = findVar(p, p->lex[GL_pos].name);
//printf("\nVarName<%s>\n", p->lex[GL_pos].name);
    if(num == p->numofVar) return NULL;
//printf("\nGetVGL_pos[%d]\n", GL_pos);
    GL_pos++;
    return newNode(l, num, NULL, NULL);
}

node_t* getD(program* p)
{
    node_t* n = NULL;
    lexeme* l;
    if(p->lex[GL_pos].lexType == OPERATOR &&
        p->lex[GL_pos].opType == DEC)
    {
        l = &(p->lex[GL_pos]);
        GL_pos++;
        if(!(p->lex[GL_pos].lexType == VARIABLE || p->lex[GL_pos].lexType == FUNCTION))
            return NULL;
        else if(p->lex[GL_pos].lexType == VARIABLE)
        {
            if (createVar(p))
                return NULL;
            p->var[p->numofVar - 1].isFunction = 0;
            n = newNode(l, 0, NULL, newNode(&(p->lex[GL_pos]), p->numofVar - 1, NULL, NULL));
            GL_pos++;
        }
        else if(p->lex[GL_pos].lexType == FUNCTION)
        {
            if (createVar(p))
                return NULL;
            p->var[p->numofVar - 1].isFunction = 1;
            lexeme* fl = &(p->lex[GL_pos]);
            GL_pos += 2;
            printf("\n<%d>\n", GL_pos);
            if (p->lex[GL_pos].lexType == OPERATOR)
                return NULL;
            else if(p->lex[GL_pos].lexType == VARIABLE && !strcmp(p->lex[GL_pos].name, "noArgsAtAll"))
                {n = newNode(l, 0, NULL, newNode(fl, p->numofVar - 1, getPr(p), NULL)); p->var[p->numofVar-1].args = 0;}
            //arg will be in function.value;
            else if(p->lex[GL_pos].lexType == VARIABLE)
            {
                lexeme* vl = &(p->lex[GL_pos]);
                GL_pos += 3;
                n = newNode(l, 0, newNode(vl, 0, NULL, NULL), newNode(fl, p->numofVar - 1, getPr(p), NULL)),
                p->var[p->numofVar-1].args = 1;
            }
        }
    }
    else
        n = getL(p);
    return n;
}

node_t* getL(program* p)
{
//printf("\nGetL\n");
    node_t* n = getV(p);
//printf("\nGetL[%p]\n",n);
//printTree(n);
    if(p->lex[GL_pos].lexType == OPERATOR && p->lex[GL_pos].opType == BR_OP)
        n->right = getF(p);
    else
        //removed about LexType opertor
        if(p->lex[GL_pos].opType == MOV)
            {GL_pos++; n = newNode(&(p->lex[GL_pos-2]), 0, n, getE(p));}
    return n;
}

node_t* getPr(program* p)
{
    node_t* n = getD(p);
    n = newNode(&p->lex[GL_pos], 0, n, NULL);
    node_t* root = n;
    lexeme* l = NULL;
    while(p->lex[GL_pos].lexType == OPERATOR &&
        p->lex[GL_pos].opType == OP && GL_pos != (p->length-2))
    {
        l = &(p->lex[GL_pos]);
        GL_pos++;
        if(p->lex[GL_pos].opType == SKIP)
        {
            GL_pos++;
            break;
        }
//n = newNode(l, 0, n, getD(p));
//printf("\nRoot[%p] n[%p] GL_pos[%d]\n", root, n, GL_pos);
//printTree(root);
//printf("\n");
        n->right = newNode(l, 0, getD(p), NULL);
        n = n->right;
    }

    printf("\nprpos<%d>", GL_pos);
    return root;
}

node_t* getF(program* p)
{
    node_t* n = NULL;
    GL_pos++;
    int fnum = findVar(p, p->lex[GL_pos-1].name);
    for(int i = 0; i < p->var[fnum].args; i++);
        n = newNode(&(p->lex[GL_pos]), findVar(p,p->lex[GL_pos].name), NULL, n), GL_pos++;
    return n;
}

node_t* getT(program* p)
{
    node_t* n = getP(p);
    lexeme* l;
//printf("getP[%p]", n);
//printTree(n);
    while(p->lex[GL_pos].lexType == OPERATOR &&
    (p->lex[GL_pos].opType == MUL || p->lex[GL_pos].opType == DIV))
    {
        l = &(p->lex[GL_pos]);
        GL_pos++;
        n = newNode(l, 0, n, getP(p));
    }
    return n;
}
node_t* newNode(lexeme* lex, int numVar, node_t* left, node_t* right)
{
    if(lex == NULL)
        return NULL;
    node_t* n = (node_t*) calloc(1, sizeof(node_t));
    n->left   = left;
    n->right  = right;
    n->numVar = numVar;
    n->lex    = lex;
//printTree(n);
//printf("\n");
    return n;
}

int createVar(program* p)
{
printf("ya zdec\n");
    if(findVar(p, p->lex[GL_pos].name) < p->numofVar)
        return 1;
    strcpy(p->var[p->numofVar].name, p->lex[GL_pos].name);
    p->var[p->numofVar].value = 0;
    ++p->numofVar;
    return 0;
}
int findVar(program* p, char temp[])
{
    int i = 0;
//printf("FindVarb\n");
    while(i < p->numofVar)
        if(!strcmp(p->var[i++].name, temp))
            return i-1;
//printf("FindVare\n");
    return i;
}

void printTree(node_t* n)
{
    if(n->left) printTree(n->left);
    printf("node[%p]l[%p]r[%p]lexType[%d],opType[%d]name<%s>,value[%lg]\n", n, n->left, n->right, n->lex->lexType, n->lex->opType, n->lex->name, n->lex->value);
    if(n->right) printTree(n->right);
}
